home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
upc12bs1.zip
/
LIB
/
execute.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-03
|
26KB
|
787 lines
/*--------------------------------------------------------------------*/
/* e x e c u t e . C */
/* */
/* Execute an external command for UUPC/extended functions */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* Changes Copyright (c) 1989-1993 by Kendra Electronic */
/* Wonderworks. */
/* */
/* All rights reserved except those explicitly granted by */
/* the UUPC/extended license agreement. */
/*--------------------------------------------------------------------*/
/*--------------------------------------------------------------------*/
/* RCS Information */
/*--------------------------------------------------------------------*/
/*
* $Id: execute.c 1.11 1993/10/03 22:09:09 ahd Exp $
*
* Revision history:
* $Log: execute.c $
* Revision 1.11 1993/10/03 22:09:09 ahd
* Change debugging messages
*
* Revision 1.10 1993/10/02 22:56:59 ahd
* Suppress compile warning
*
* Revision 1.9 1993/10/02 19:07:49 ahd
* Suppress compiler warning
*
* Revision 1.8 1993/09/27 00:45:20 ahd
* Fix Windows compile, add debug to OS/2 and DOS version
*
* Revision 1.7 1993/09/26 03:32:27 dmwatt
* Use Standard Windows NT error message module
*
* Revision 1.6 1993/09/23 03:26:51 ahd
* Use common file search routine
*
* Revision 1.5 1993/09/20 04:38:11 ahd
* TCP/IP support from Dave Watt
* 't' protocol support
* OS/2 2.x support
*
* Revision 1.4 1993/08/08 17:39:09 ahd
* Denormalize path for opening on selected networks
*
* Revision 1.3 1993/08/03 03:11:49 ahd
* Further Windows 3.x fixes
*
* Revision 1.2 1993/08/02 03:24:59 ahd
* Further changes in support of Robert Denny's Windows 3.x support
*
* Revision 1.1 1993/07/31 16:22:16 ahd
* Initial revision
*
*/
/*--------------------------------------------------------------------*/
/* System include files */
/*--------------------------------------------------------------------*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <process.h>
#include <io.h>
#ifdef WIN32
#include <windows.h>
#include <signal.h>
#elif defined(_Windows)
#include <windows.h>
#include <shellapi.h>
#endif
#include <direct.h>
/*--------------------------------------------------------------------*/
/* UUPC/extended include files */
/*--------------------------------------------------------------------*/
#include "lib.h"
#include "hlib.h"
#include "execute.h"
#ifdef _Windows
#include "winutil.h"
#endif
#ifdef WIN32
#include "pnterr.h"
#endif
/*--------------------------------------------------------------------*/
/* Local variables */
/*--------------------------------------------------------------------*/
currentfile();
/*--------------------------------------------------------------------*/
/* Internal function prototypes */
/*--------------------------------------------------------------------*/
static boolean internal( const char *command );
static boolean batch( const char *input, char *output);
#ifdef _Windows
/*--------------------------------------------------------------------*/
/* e x e c u t e (Windows 3.x version) */
/* */
/* execute external command under Windows */
/*--------------------------------------------------------------------*/
int execute( const char *command,
const char *parameters,
const char *input,
const char *output,
const boolean synchronous,
const boolean foreground )
{
int result;
boolean useBat = (input != NULL) || (output != NULL );
char path[FILENAME_MAX]; /* String for executable file */
char batchFile[FILENAME_MAX]; /* String for batch driver file */
char perfect[FILENAME_MAX]; /* String for results test file */
/*--------------------------------------------------------------------*/
/* Locate the command */
/*--------------------------------------------------------------------*/
if ( internal( command ) )
{
strcpy( path , command );
useBat = TRUE;
}
else if (batch( command, path ))
{
if (useBat) // Using redirection?
{
printmsg(0,"Cannot use redirection with batch file %s",
path );
return -2;
}
} /* else */
else if ( !*path ) // Error returned from search?
return -1; // Yes --> Error already reported
/*--------------------------------------------------------------------*/
/* Generate a batch file for redirected DOS programs, if needed */
/*--------------------------------------------------------------------*/
if ( useBat )
{
FILE *stream ;
mktempname( batchFile, "BAT");
mktempname( perfect, "TMP");
stream = FOPEN( batchFile, "w", TEXT_MODE );
if ( stream == NULL )
{
printerr( batchFile );
panic();
}
fprintf( stream ,
"@echo off\n%s %s",
path,
parameters == NULL ? "" : parameters );
if ( input != NULL )
fprintf( stream, " < %s", input );
if ( output != NULL )
fprintf( stream, " < %s", output );
fprintf( stream,
"\nif errorlevel 1 erase %s\n",
perfect );
fclose ( stream );
stream = FOPEN( perfect, "w", TEXT_MODE );
if ( stream == NULL )
{
printerr( perfect );
panic();
}
fclose( stream );
strcpy( path, batchFile ); // Run the batch command
} /* if ( useBat ) */
/*--------------------------------------------------------------------*/
/* Actually run the command */
/*--------------------------------------------------------------------*/
result = SpawnWait( path,
parameters,
synchronous,
foreground ? SW_MAXIMIZE : SW_SHOWMINNOACTIVE );
/*--------------------------------------------------------------------*/
/* For batch files, we can only report zero/non-zero */
/* results. Do so, and clean up our input file at the same */
/* time. */
/*--------------------------------------------------------------------*/
if ( useBat )
{
int unlinkResult = unlink( perfect );
if (( result == 0 ) && (unlinkResult != 0))
result = 255;
if (unlink( batchFile ))
printerr( batchFile );
} /* if ( useBat ) */
/*--------------------------------------------------------------------*/
/* Report results of command */
/*--------------------------------------------------------------------*/
printmsg( 4,"Result of spawn %s is ... %d", command, result);
return result;
} /* execute */
#elif defined(WIN32)
/*--------------------------------------------------------------------*/
/* e x e c u t e (Windows NT version) */
/* */
/* Execute an external program */
/*--------------------------------------------------------------------*/
int execute( const char *command,
const char *parameters,
const char *input,
const char *output,
const boolean synchronous,
const boolean foreground )
{
int result;
char path[BUFSIZ];
/*--------------------------------------------------------------------*/
/* Redirect STDIN and STDOUT as required */
/*--------------------------------------------------------------------*/
if ((input != NULL) && (freopen(input , "rb", stdin) == NULL))
{
printerr(input);
return -2;
}
if ((output != NULL) && (freopen(output, "wt", stdout) == NULL))
{
printerr( output );
if ( input != NULL )
{
FILE *temp = freopen("con", "rt", stdin);
if ( (temp == NULL) && (errno != 0) )
{
printerr("stdin");
panic();
}
setvbuf( stdin, NULL, _IONBF, 0);
} /* if ( input != NULL ) */
return -2;
}
/*--------------------------------------------------------------------*/
/* Execute the command in question */
/*--------------------------------------------------------------------*/
if (internal(strcpy(path,command)) ||
batch(command, path)) // Internal or batch command?
{
if ( parameters == NULL )
result = system( path );
else {
strcat( path, " ");
strcat( path, parameters );
result = system( path );
} /* else */
} /* if (internal(command)) */
else { /* No --> Invoke normally */
STARTUPINFO si;
PROCESS_INFORMATION pi;
void *oldCtrlCHandler;
if ( ! *path ) // Did search fail?
return -2; // Yes --> Msg issued, just return
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpTitle = (LPSTR)command;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = foreground ? SW_MAXIMIZE : SW_SHOWMINNOACTIVE;
if (parameters != NULL)
{
strcat( path, " ");
strcat( path, parameters );
}
result = CreateProcess(NULL,
path,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si,
&pi);
if (!result) // Did CreateProcess() fail?
{ // Yes --> Report error
DWORD dwError = GetLastError();
printmsg(0, "execute: CreateProcess failed");
printNTerror("CreateProcess", dwError);
}
else {
if (synchronous)
{
/*--------------------------------------------------------------------*/
/* Set things up so that we ignore Ctrl-C's coming in to the */
/* child, and wait for other application to finish. */
/*--------------------------------------------------------------------*/
oldCtrlCHandler = signal(SIGINT, SIG_IGN);
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &result);
signal(SIGINT, oldCtrlCHandler); // Re-enable Ctrl-C handling
} /* if (synchronous) */
else
result = 0;
/*--------------------------------------------------------------------*/
/* If we're spawning asynchronously, we assume that we don't */
/* care about the exit code from the spawned process. */
/* Closing these makes it impossible to get at the old */
/* process's exit code. */
/*--------------------------------------------------------------------*/
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
} /* else !result */
} /* else internal command */
/*--------------------------------------------------------------------*/
/* Re-open our standard i/o streams */
/*--------------------------------------------------------------------*/
if ( output != NULL )
{
freopen("con", "wt", stdout);
setvbuf( stdout, NULL, _IONBF, 0);
}
if ( input != NULL )
{
FILE *temp = freopen("con", "rt", stdin);
if ( (temp == NULL) && (errno != 0) )
{
printerr("stdin");
panic();
}
setvbuf( stdin, NULL, _IONBF, 0);
} /* if ( input != NULL ) */
/*--------------------------------------------------------------------*/
/* Report results of command */
/*--------------------------------------------------------------------*/
printmsg( 4 ,"Result of spawn %s is ... %d", command, result);
return result;
} /* execute */
#else
#ifdef __TURBOC__
#pragma argsused
#endif
/*--------------------------------------------------------------------*/
/* e x e c u t e (OS/2 + DOS version) */
/* */
/* Generic execute external command with optional redirection */
/* of standard input and output */
/*--------------------------------------------------------------------*/
int execute( const char *command,
const char *parameters,
const char *input,
const char *output,
const boolean synchronous,
const boolean foreground )
{
int result;
char path[BUFSIZ];
/*--------------------------------------------------------------------*/
/* Redirect STDIN and STDOUT as required */
/*--------------------------------------------------------------------*/
if ((input != NULL) && (freopen(input , "rb", stdin) == NULL))
{
printerr(input);
return -2;
}
if ((output != NULL) && (freopen(output, "wt", stdout) == NULL))
{
printerr( output );
if ( input != NULL )
{
FILE *temp = freopen("con", "rt", stdin);
if ( (temp == NULL) && (errno != 0) )
{
printerr("stdin");
panic();
}
setvbuf( stdin, NULL, _IONBF, 0);
} /* if ( input != NULL ) */
return -2;
}
/*--------------------------------------------------------------------*/
/* Execute the command in question */
/*--------------------------------------------------------------------*/
if (internal(strcpy(path,command)) ||
batch(command,path)) // Internal command or batch file?
{
if ( parameters == NULL )
result = system( path );
else {
strcat( path, " ");
strcat( path, parameters );
result = system( path );
} /* else */
} /* if (internal(command)) */
else { /* No --> Invoke normally */
if ( *path )
{
printmsg(4,"execute: spawnlp(%d, %s, %s%s%s)",
synchronous ? P_WAIT : P_NOWAIT,
path,
command,
parameters == NULL ? "" : ", ",
parameters == NULL ? "" : parameters );
result = spawnlp( synchronous ? P_WAIT : P_NOWAIT,
(char *) path,
(char *) command,
(char *) parameters,
NULL);
if (result == -1) /* Did spawn fail? */
printerr(command); /* Yes --> Report error */
} /* else */
else
result = -3; // Flag we never ran command
} /* else */
/*--------------------------------------------------------------------*/
/* Re-open our standard i/o streams */
/*--------------------------------------------------------------------*/
if ( output != NULL )
{
freopen("con", "wt", stdout);
setvbuf( stdout, NULL, _IONBF, 0);
}
if ( input != NULL )
{
FILE *temp = freopen("con", "rt", stdin);
if ( (temp == NULL) && (errno != 0) )
{
printerr("stdin");
panic();
}
setvbuf( stdin, NULL, _IONBF, 0);
} /* if ( input != NULL ) */
/*--------------------------------------------------------------------*/
/* Report results of command */
/*--------------------------------------------------------------------*/
printmsg( 4,"Result of spawn %s is ... %d", command, result);
return result;
} /* execute */
#endif
/*--------------------------------------------------------------------*/
/* e x e c u t e C o m m a n d */
/* */
/* Split command from its parameters for execute */
/*--------------------------------------------------------------------*/
int executeCommand( const char *command,
const char *input,
const char *output,
const boolean synchronous,
const boolean foreground )
{
char *cmdname;
char *parameters;
char buffer[FILENAME_MAX];
int result;
strcpy( buffer, command );
cmdname = strtok( buffer, WHITESPACE );
parameters = strtok( NULL, "\r\n" );
if ( parameters != NULL )
{
while (isspace( *parameters ) || iscntrl( *parameters ))
parameters++;
if ( !strlen( parameters ))
parameters = NULL;
}
result = execute( cmdname,
parameters,
input,
output,
synchronous,
foreground );
return result;
} /* executeCommand */
/*--------------------------------------------------------------------*/
/* i n t e r n a l */
/* */
/* Determine if command is internal DOS command */
/*--------------------------------------------------------------------*/
static boolean internal( const char *command )
{
static char *commands[] = { "break", "cd", "chdir", "copy",
"ctty", "date", "del", "dir",
"echo", "erase", "for", "md",
"mkdir", "rd", "rem", "ren",
"rename", "rmdir", "time", "ver",
"verify", "vol",
NULL };
char **list;
/*--------------------------------------------------------------------*/
/* Determine command list to use */
/*--------------------------------------------------------------------*/
if (E_internal == NULL )
list = commands;
else
list = E_internal;
/*--------------------------------------------------------------------*/
/* Scan the list for the command */
/*--------------------------------------------------------------------*/
while( *list != NULL )
{
printmsg(5,"Searching for \"%s\", comparing to \"%s\"",
*list, command);
if (equali(*list++,command))
{
printmsg(4,"\"%s\" is an internal command",command);
return TRUE;
} /* if */
} /* while( *list != NULL ) */
/*--------------------------------------------------------------------*/
/* The command is not in the list; return FALSE (external */
/* command) */
/*--------------------------------------------------------------------*/
printmsg(4,"\"%s\" is an external command",command);
return FALSE;
} /* internal */
/*--------------------------------------------------------------------*/
/* b a t c h */
/* */
/* Determine if a command is batch file */
/*--------------------------------------------------------------------*/
static boolean batch( const char *input, char *output)
{
char *search = getenv("PATH");
char *gotPath;
char *period;
static const char *extensions[] = { ".exe",
".com",
#if !defined(_DOS) && !defined(_Windows)
".cmd",
#endif
".bat",
NULL };
/*--------------------------------------------------------------------*/
/* Validate the search path exists */
/*--------------------------------------------------------------------*/
if ( search == NULL )
{
printmsg(0,"batch: Unable to retrieve PATH environment variable!");
panic();
}
/*--------------------------------------------------------------------*/
/* Determine if we have path, and if we have an extension */
/*--------------------------------------------------------------------*/
gotPath = strchr( input, '/');
if ( gotPath == NULL )
gotPath = strchr( input, '\\');
period = strchr( (gotPath == NULL) ? input : gotPath, '.');
if ( period != NULL ) // We have extension?
{
if ( gotPath ) // Extension + path?
{ // Yes --> Just look for the file
char *fname = normalize( input );
if ( access( input, 00))
*output = '\0';
else
strcpy( output, fname );
} /* if ( gotPath ) */
else
_searchenv( input, "PATH", output );
if ( ! *output ) // No file found?
{
printerr( input );
return FALSE;
} /* if ( ! *output ) */
#if defined(_DOS) || defined(_Windows)
return equal( period, ".bat" );
#else
return equali( period, ".cmd" ) || equali( period, ".bat" );
#endif
} /* if ( p != NULL ) */
/*--------------------------------------------------------------------*/
/* Walk the path looking for the file's possible types in */
/* the path's directories */
/*--------------------------------------------------------------------*/
while( *search )
{
char base[FILENAME_MAX];
int extension = 0;
if ( gotPath )
{
strcpy( base, input );
search = ""; // Force this to be last pass
}
else {
char *next = strchr(search,';'); // Find next path component
size_t len;
if ( next == NULL )
len = strlen( search );
else
len = (size_t) (next - search);
memcpy( base, search, len ); // Path for search ...
search += len + 1; // Step past semicolon
if ( base[len - 1 ] != '\\' ) // Ending in back slash?
base[len++] = '\\'; // No --> Add one
strcpy( base + len , input ); // ... plus file name
} /* else */
printmsg(8,
"Searching for extension of %s",
base );
/*--------------------------------------------------------------------*/
/* Search a single directory in a path for a file with */
/* various extensions. */
/*--------------------------------------------------------------------*/
while( extensions[extension] != NULL )
{
strcpy( output, base );
strcat( output, extensions[extension] );
if ( ! access(output, 00 ))
{
#if defined(_DOS) || defined(_Windows)
return equal( extensions[extension] , ".bat" );
#else
return equal( extensions[extension] , ".cmd" ) ||
equal( extensions[extension] , ".bat" );
#endif
} /* if ( result != NULL ) */
extension++;
} /* while( extensions[extension] != NULL ) */
} /* while( *search ) */
/*--------------------------------------------------------------------*/
/* We could not find the file, report failure to the caller */
/*--------------------------------------------------------------------*/
printmsg(0, "batch: Unable to locate %s in search path", input);
*output = '\0'; // Flag no file found!
return FALSE;
} /* batch */